//
//  MFAExceptionNetwork.m
//  NewMissFresh
//
//  Created by 董宝君 on 2019/6/19.
//  Copyright © 2019 com.missfresh. All rights reserved.
//

#import "MFAExceptionNetwork.h"
#import "MFALogger.h"

typedef void(^MFAURLSessionTaskCompletionHandler)(NSData * _Nullable data, NSHTTPURLResponse * _Nullable response, NSError * _Nullable error);

@interface MFAExceptionNetwork ()<NSURLSessionDelegate, NSURLSessionTaskDelegate>

/**
 网络请求线程回调的队列
 */
@property (nonatomic, strong) NSOperationQueue *operationQueue;

/**
 当前请求的session对象
 */
@property (nonatomic, strong) NSURLSession *session;

/**
 用于评价请求是否是服务器信任的链接，默认为：defaultPolicy 暂且不提供给外部设置
 */
@property (nonatomic, strong) MFASecurityPolicy *securityPolicy;

@end

@implementation MFAExceptionNetwork

- (instancetype)init {
    if(self = [super init]){
        [self commonInit];
    }
    return self;
}

- (instancetype)initWithServerURL:(NSURL *)serverURL {
    if(self = [super init]){
        [self commonInit];
        _serverURL = serverURL;
    }
    return self;
}

- (void)commonInit {
    _securityPolicy = [MFASecurityPolicy defaultPolicy];
    _operationQueue = [[NSOperationQueue alloc] init];
    _operationQueue.maxConcurrentOperationCount = 1;
}

- (NSURLSession *)session {
    @synchronized (self) {
        if (!_session) {
            NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
            config.timeoutIntervalForRequest = 10.0;
            config.HTTPShouldUsePipelining = NO;
            _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:self.operationQueue];
        }
    }
    return _session;
}

#pragma mark - public

- (BOOL)reportException:(NSString *)exception {
    if(!self.serverURL){
        MFAError(@"serverURL error，Please check the serverURL");
        return NO;
    }
    
    //拼接json字符串
    NSString *jsonString = [self buildFlushJSONStringWithException:exception];
    
    __block BOOL flushSuccess = NO;
    dispatch_semaphore_t flushSemaphore = dispatch_semaphore_create(0);
    MFAURLSessionTaskCompletionHandler handler = ^(NSData * _Nullable data, NSHTTPURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error || ![response isKindOfClass:[NSHTTPURLResponse class]]) {
            MFAError(@"%@", [NSString stringWithFormat:@"%@ network failure: %@", self, error ? error : @"Unknown error"]);
            dispatch_semaphore_signal(flushSemaphore);
            return;
        }
        
        NSString *urlResponseContent = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSInteger statusCode = response.statusCode;
        MFAError(@"==========================================================================");
        if (statusCode != 200) {
            MFAError(@"%@ ret_code: %ld", self, statusCode);
            MFAError(@"%@ ret_content: %@", self, urlResponseContent);
        }
        
        id responseObject = nil;
        NSError *serializationError = nil;
        
        //只有判断数据到达了服务端，返回了{"message":"ok", "code":0}对应的数据格式，就可以当做成功，删除数据
        BOOL isSpace = [data isEqualToData:[NSData dataWithBytes:" " length:1]];
        if (data.length > 0 && !isSpace) {
            responseObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&serializationError];
            if(!serializationError && responseObject && [responseObject isKindOfClass:[NSDictionary class]]){
                NSDictionary *responseDict = (NSDictionary *)responseObject;
                if([[responseDict allKeys] containsObject:@"errcode"]){
                    flushSuccess = YES;
                }else{
                    flushSuccess = NO;
                }
            }else{
                flushSuccess = NO;
            }
        } else {
            flushSuccess = NO;
        }
        
        dispatch_semaphore_signal(flushSemaphore);
    };
    
    NSURLRequest *request = [self buildFlushRequestWithJSONString:jsonString HTTPMethod:@"POST"];
    NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:handler];
    [task resume];
    
    dispatch_semaphore_wait(flushSemaphore, DISPATCH_TIME_FOREVER);
    
    return flushSuccess;
}

#pragma mark - build
//拼接json字符串 注意需要修改，不要数组，要拼接成字典
- (NSString *)buildFlushJSONStringWithException:(NSString *)exception {
    return exception;
}

- (NSURLRequest *)buildFlushRequestWithJSONString:(NSString *)jsonString HTTPMethod:(NSString *)HTTPMethod {
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.serverURL];
    request.timeoutInterval = 10;
    request.HTTPMethod = HTTPMethod;
    NSString *postBody = [jsonString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    postBody = [NSString stringWithFormat:@"param=%@",postBody];
    request.HTTPBody = [postBody dataUsingEncoding:NSUTF8StringEncoding];
    [request setValue:@"application/x-www-form-urlencoded;charset=utf-8" forHTTPHeaderField:@"Content-Type"];

    return request;
}

#pragma mark - request

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(MFAURLSessionTaskCompletionHandler)completionHandler {
    return [self.session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error || ![response isKindOfClass:[NSHTTPURLResponse class]]) {
            return completionHandler(nil, nil, error);
        }
        return completionHandler(data, (NSHTTPURLResponse *)response, error);
    }];
}

#pragma mark - NSURLSessionDelegate
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
    NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    __block NSURLCredential *credential = nil;
    
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
            credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            if (credential) {
                disposition = NSURLSessionAuthChallengeUseCredential;
            } else {
                disposition = NSURLSessionAuthChallengePerformDefaultHandling;
            }
        } else {
            disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
        }
    } else {
        disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    }
    
    if (completionHandler) {
        completionHandler(disposition, credential);
    }
}

#pragma mark - NSURLSessionTaskDelegate
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
    NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    __block NSURLCredential *credential = nil;
    
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
            disposition = NSURLSessionAuthChallengeUseCredential;
            credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
        } else {
            disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
        }
    } else {
        disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    }
    
    if (completionHandler) {
        completionHandler(disposition, credential);
    }
}


@end
